/// 辅助 * 缓存

import { getStorageItem, removeStorageItem, setStorageItem } from '@expresso/plus'
import { upperFirst } from 'lodash-es'
import { getConfig } from './config'

//# 类型

type CacheConver<T extends Entity> = {
  [K in keyof T as `get${Capitalize<K & string>}`]-?: () => T[K];
} & {
  [K in keyof T as `set${Capitalize<K & string>}`]-?:
  (value?: T[K]) => CacheConver<T>;
} & {
  [K in keyof T as `remove${Capitalize<K & string>}`]-?:
  () => CacheConver<T>;
} & {
  clear: (scope?: 'local' | 'session' | 'all') => CacheConver<T>
}

type CacheKeys = (keyof CacheType)[]
type CacheType = Window['__demo__']['cache']
type CacheReturn = CacheConver<CacheType>

//# 定义

const cacheKeysLocal = ['token'] as CacheKeys
const cacheKeysSession = [] as CacheKeys

const cache = {
  ...initCache(cacheKeysLocal),
  ...initCache(cacheKeysSession, false),
  clear(scope = 'local') {
    if (['local', 'all'].includes(scope)) {
      cacheKeysLocal.forEach((key) => {
        delete window.__demo__.cache[key]
        removeStorageItem(key)
      })
    }
    if (['session', 'all'].includes(scope)) {
      cacheKeysLocal.forEach((key) => {
        delete window.__demo__.cache[key]
        removeStorageItem(key, false)
      })
    }
  },
} as CacheReturn

function initCache(cacheKeys: CacheKeys, isLocalStorage = true): CacheReturn {
  const cache: any = {}
  const cacheData = (
    getConfig().cache ? getConfig().cache : getConfig().cache = shallowReactive({}) as CacheType
  )
  cacheKeys.forEach((key) => {
    const value = getStorageItem(key, isLocalStorage)
    if (value !== void 0) {
      cacheData[key] = value
    }
    //* get
    cache[`get${upperFirst(key)}`] = (isLocalStorage = true) => {
      return Reflect.has(cacheData, key) ? cacheData[key] : getStorageItem(key, isLocalStorage)
    }
    //* set
    cache[`set${upperFirst(key)}`] = (value: any) => {
      cacheData[key] = value
      setStorageItem(key, value, isLocalStorage)
      return cache
    }
    //* remove
    cache[`remove${upperFirst(key)}`] = () => {
      delete cacheData[key]
      removeStorageItem(key, isLocalStorage)
      return cache
    }
  })
  return cache as CacheReturn
}

//# 导出

export { cache }
